<template>
  <div>
    <el-form v-if="fieldItem" label-width="110px" label-position="left" size="small">
      <el-tabs v-model="activeName">
        <el-tab-pane label="字段配置" name="mysql">
          <div class="tab-pane-content">
            <el-form-item label="生成类型">
              <el-select v-model="fieldItem.designType" placeholder="请选择">
                <el-option v-for="item in designTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
              <div class="dk-help">当前选项中仅有部分会生效，具体渲染在表格和表单中配置</div>
            </el-form-item>
            <el-form-item v-if="fieldItem.designType === 'remoteSelect' || fieldItem.designType === 'remoteSelects'" label="远程字段配置">
              <el-button v-if="!fieldItem.remoteConfig?.table" type="danger" @click="dialogVisible = true"> 未配置，点击配置 </el-button>
              <el-button v-else type="success" @click="dialogVisible = true"> 已配置({{ fieldItem.remoteConfig.table }}) </el-button>
              <el-dialog v-model="dialogVisible" title="远程选择配置" width="660px" top="10vh" append-to-body>
                <remote-form
                  v-if="addon.name"
                  :value="fieldItem.remoteConfig"
                  :addon="addon"
                  :field-item="fieldItem"
                  @submit="remoteSubmit"
                />
              </el-dialog>
            </el-form-item>
            <el-form-item label="字段名称">
              <el-input v-model="fieldItem.name" />
            </el-form-item>
            <el-form-item label="字段注释">
              <el-input v-model="fieldItem.comment" type="textarea" />
              <span class="dk-help"
                >注释和表名称会自动转换，详细：<el-link
                  type="primary"
                  style="font-size: 12px"
                  target="_blank"
                  href="https://doc.dkyx.cc/vue3/guide/databaseSpecification/"
                  >点击这里</el-link
                ></span
              >
            </el-form-item>

            <el-form-item label="字段类型">
              <el-select v-model="fieldItem.type" placeholder="请选择" style="width: 100%" filterable>
                <el-option v-for="t in mysqlTypeOptions" :key="t" :label="t" :value="t" />
              </el-select>
            </el-form-item>
            <el-row :gutter="20">
              <el-col :span="24">
                <el-form-item label="长度">
                  <template v-if="fieldItem.type === 'enum' || fieldItem.type === 'set'">
                    <EnumSetInput v-model="fieldItem.length" />
                  </template>
                  <template v-else>
                    <el-input v-model="fieldItem.length" />
                    <span class="dk-help">支持数字；当类型为 enum/set 时，请填写如：'0','1'</span>
                  </template>
                </el-form-item>
              </el-col>
              <!-- <el-col :span="12">
                <el-form-item label="小数点">
                  <el-input v-model="fieldItem.precision" />
                </el-form-item>
              </el-col> -->
            </el-row>
            <template v-if="fieldItem.type === 'enum' || fieldItem.type === 'set'">
              <el-form-item label="默认值类型">
                <el-input value="INPUT" disabled />
                <span class="dk-help">枚举/集合默认值仅能从可选项中选择</span>
              </el-form-item>
              <el-form-item label="字段默认值">
                <el-select
                  v-if="fieldItem.type === 'enum'"
                  v-model="enumDefaultSingle"
                  placeholder="请选择默认值"
                  style="width: 100%"
                  :clearable="true"
                >
                  <el-option v-for="opt in enumSetOptions" :key="opt" :label="opt" :value="opt" />
                </el-select>
                <el-select
                  v-else
                  v-model="enumDefaultMultiple"
                  placeholder="请选择默认值"
                  style="width: 100%"
                  multiple
                  collapse-tags
                  :clearable="true"
                >
                  <el-option v-for="opt in enumSetOptions" :key="opt" :label="opt" :value="opt" />
                </el-select>
              </el-form-item>
            </template>
            <template v-else>
              <el-form-item label="默认值类型">
                <el-select v-model="fieldItem.defaultType" placeholder="请选择" style="width: 100%">
                  <el-option v-for="item in defaultTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
                </el-select>
              </el-form-item>
              <el-form-item v-if="fieldItem.defaultType === 'INPUT'" label="字段默认值">
                <el-input v-model="fieldItem.default" />
              </el-form-item>
            </template>
            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item label="主键">
                  <el-switch v-model="fieldItem.primaryKey" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="自动递增">
                  <el-switch v-model="fieldItem.autoIncrement" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="无符号(非负数)">
                  <el-switch v-model="fieldItem.unsigned" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="允许NULL">
                  <el-switch v-model="fieldItem.null" />
                </el-form-item>
              </el-col>
              <el-col :span="24">
                <el-form-item label="字段类型转换">
                  <el-select v-model="fieldItem.modelType" placeholder="请选择" style="width: 100%" clearable>
                    <el-option v-for="item in modelTypeOption" :key="item.value" :label="item.label" :value="item.value" />
                  </el-select>
                  <span class="dk-help"
                    >设置字段类型转换。
                    <el-link href="https://doc.thinkphp.cn/v8_0/type_conversion.html" target="_blank" type="primary" style="font-size: 12px"
                      >参考文档</el-link
                    ></span
                  >
                </el-form-item>
              </el-col>
            </el-row>
            <el-form-item label="备注">
              <el-input v-model="fieldItem.desc" type="textarea" :rows="4" />
            </el-form-item>
          </div>
        </el-tab-pane>
        <el-tab-pane label="表格配置" name="table">
          <div v-if="fieldItem.table" class="tab-pane-content">
            <el-form-item label="是否移除">
              <el-switch v-model="fieldItem.table.filter" />
              <span class="dk-help">移除后将不再显示当前列</span>
            </el-form-item>
            <template v-if="!fieldItem.table.filter">
              <p style="padding: 10px 0; font-weight: bold">表格字段配置</p>
              <p style="font-size: 12px; color: #999; padding-bottom: 10px">
                设置数据表格的字段配置，配置项除了一些特殊的配置外，其余的应用在Element的
                <el-link
                  href="https://element-plus.org/zh-CN/component/table.html#table-column-%E5%B1%9E%E6%80%A7"
                  target="_blank"
                  type="primary"
                  style="font-size: 12px"
                >
                  Table-column 属性
                </el-link>
                。
              </p>
              <el-form-item label="渲染方案">
                <el-select v-model="fieldItem.table.render" placeholder="请选择">
                  <el-option v-for="item in tableRenderOption" :key="item.value" :label="item.label" :value="item.value" />
                </el-select>
              </el-form-item>
              <el-form-item v-if="fieldItem.table.render === 'slot'" label="搜索插槽名">
                <el-input v-model="fieldItem.table.slotName" placeholder="填写插槽名称" />
                <span class="dk-help">设置插槽名称，不填将默认为{{ fieldItem.name + '_slot' }}</span>
              </el-form-item>
              <el-form-item v-if="fieldItem.table.render === 'customRender'" label="搜索自定义组件">
                <el-input v-model="fieldItem.table.component" placeholder="填写自定义组件名称" />
                <span class="dk-help">自定义组件接收props:render-row、render-field、render-value、render-column、render-index</span>
              </el-form-item>
              <el-form-item label="字段宽度">
                <el-input v-model="fieldItem.table.width" placeholder="填写字段表格宽度" />
                <span class="dk-help">设置对应列的宽度，例如：150px</span>
              </el-form-item>
              <el-form-item label="启用排序">
                <el-switch v-model="fieldItem.table.sortable" />
              </el-form-item>
              <!--              <el-form-item label="渲染方案">-->
              <!--                <el-select v-model="fieldItem.table.render" placeholder="请选择">-->
              <!--                  <el-option-->
              <!--                    v-for="item in renderOptions"-->
              <!--                    :key="item.value"-->
              <!--                    :label="item.label"-->
              <!--                    :value="item.value"-->
              <!--                  />-->
              <!--                </el-select>-->
              <!--              </el-form-item>-->

              <el-form-item label="列字段标题">
                <el-input v-model="fieldItem.table.label" placeholder="填写表格的字段名，不填为默认" />
                <span class="dk-help">设置表格对应列的标题，也就是label属性</span>
              </el-form-item>
              <el-form-item label="是否默认隐藏">
                <el-switch v-model="fieldItem.table.hidden" />
                <span class="dk-help">开启后，当前列将默认隐藏</span>
              </el-form-item>
              <p style="padding: 10px 0; font-weight: bold">表格搜索配置</p>
              <el-form-item label="搜索操作符">
                <el-select v-model="fieldItem.table.operator" placeholder="请选择" clearable>
                  <el-option v-for="item in operatorOptions" :key="item.value" :label="item.label" :value="item.value" />
                </el-select>
                <div class="dk-help">范围类会自动转换为两个填框，空类会转换为单选</div>
              </el-form-item>
              <el-form-item label="搜索渲染方式">
                <!-- 'remoteSelect' | 'select' | 'date' | 'customRender' | 'slot'-->
                <el-select v-model="fieldItem.table.comSearchRender" placeholder="请选择" clearable>
                  <el-option v-for="item in comSearchRenderOptions" :key="item.value" :label="item.label" :value="item.value" />
                </el-select>
                <div class="dk-help">设置搜索框的渲染方式，一般情况下，搜索框会根据字段名或操作符自动判断</div>
              </el-form-item>
              <el-form-item v-if="fieldItem.table.comSearchRender === 'slot'" label="搜索插槽名">
                <el-input v-model="fieldItem.table.comSearchSlotName" placeholder="填写插槽名称" />
              </el-form-item>
              <el-form-item v-if="fieldItem.table.comSearchRender === 'customRender'" label="搜索自定义组件">
                <el-input v-model="fieldItem.table.comSearchComponent" placeholder="填写自定义组件名称" />
              </el-form-item>
              <el-form-item label="搜索占位符">
                <el-input v-model="fieldItem.table.operatorPlaceholder" placeholder="填写搜索框占位内容" />
              </el-form-item>
              <el-form-item label="搜索字段名称">
                <el-input v-model="fieldItem.table.comSearchLabel" placeholder="填写搜索字段名称，不填则显示默认" />
              </el-form-item>
            </template>
          </div>
        </el-tab-pane>
        <el-tab-pane label="表单配置" name="form">
          <div v-if="fieldItem.form" class="tab-pane-content">
            <el-form-item label="是否移除">
              <el-switch v-model="fieldItem.form.filter" />
            </el-form-item>
            <template v-if="!fieldItem.form.filter">
              <el-form-item label="生成类型">
                <el-select v-model="fieldItem.form.render" placeholder="请选择">
                  <el-option v-for="item in formRenderOption" :key="item.value" :label="item.label" :value="item.value" />
                </el-select>
              </el-form-item>
              <el-form-item label="是否必填">
                <el-switch v-model="fieldItem.form.required" />
              </el-form-item>
              <el-form-item label="表单标题">
                <el-input v-model="fieldItem.form.Title" placeholder="填写字段表单标题" />
                <span class="dk-help">设置表单标题</span>
              </el-form-item>
              <el-form-item label="帮助内容">
                <el-input v-model="fieldItem.form.help" placeholder="填写字段表单帮助内容" />
                <span class="dk-help">表单的帮助内容，将显示到对应表单下面</span>
              </el-form-item>
              <el-form-item label="验证规则">
                <el-select v-model="fieldItem.form.validate" placeholder="请选择" multiple>
                  <el-option v-for="item in validateOptions" :key="item.value" :label="item.label" :value="item.value" />
                </el-select>
                <div class="dk-help">设置验证规则后，当前表单默认为必填项</div>
              </el-form-item>
              <el-form-item label="验证错误提示">
                <el-input v-model="fieldItem.form.message" placeholder="填写效验错误提示" />
                <span class="dk-help">如果效验未通过，提示什么内容</span>
              </el-form-item>
              <el-form-item label="联动表单">
                <form-tab-form
                  v-model="fieldItem.form.controlFields"
                  :field-items-option="fieldItemsOption"
                  add-text="添加联动数据"
                  default-label="1"
                />
                <span class="dk-help">添加联动数据，左边表示值，右边表示显示的字段</span>
              </el-form-item>
            </template>
          </div>
        </el-tab-pane>
      </el-tabs>
    </el-form>
  </div>
</template>
<script setup>
import { computed, ref, defineOptions, watch } from 'vue'
import { designTypeOptions, formRenderOption, tableRenderOption } from '@/views/crud/crud/crud'
import RemoteForm from '@/views/crud/components/remoteForm.vue'
import FormTabForm from '@/views/crud/components/formTabForm.vue'
import EnumSetInput from '@/views/crud/components/EnumSetInput.vue'

defineOptions({ name: 'CrudForm' })

const props = defineProps({
  modelValue: { type: Object, default: () => ({}) },
  addon: { type: Object, default: () => ({}) },
  fieldItems: { type: Array, default: () => [] }
})

const emit = defineEmits(['update:modelValue'])

const dialogVisible = ref(false)
const activeName = ref('mysql')

const fieldItem = computed({
  get() {
    return props.modelValue
  },
  set(v) {
    emit('update:modelValue', v)
  }
})

const defaultTypeOptions = [
  { label: '手动输入', value: 'INPUT' },
  { label: '空字符串', value: 'EMPTY STRING' },
  { label: 'NULL', value: 'NULL' },
  { label: '不设置默认值', value: 'NONE' }
]

const renderOptions = [
  { value: 'none', label: '无' },
  { value: 'customRender', label: '自定义渲染组件' },
  { value: 'slot', label: '使用插槽' },
  { value: 'icon', label: 'Icon' },
  { value: 'switch', label: '开关' },
  { value: 'image', label: '图片' },
  { value: 'images', label: '多图' },
  { value: 'tag', label: '标签' },
  { value: 'tags', label: '多标签' },
  { value: 'url', label: '网址' },
  { value: 'datetime', label: '日期' },
  { value: 'color', label: '颜色' }
]

const operatorOptions = [
  { value: 'false', label: '禁用' },
  { value: 'eq', label: '= 等于' },
  { value: 'ne', label: '!= 不等于' },
  { value: 'gt', label: '> 大于' },
  { value: 'egt', label: '>= 大于等于' },
  { value: 'lt', label: '< 小于' },
  { value: 'elt', label: '<= 小于等于' },
  { value: 'LIKE', label: 'LIKE 模糊匹配' },
  { value: 'NOT LIKE', label: 'NOT LIKE 模糊匹配' },
  { value: 'IN', label: 'IN 包含' },
  { value: 'NOT IN', label: 'NOT IN 不包含' },
  { value: 'RANGE', label: 'RANGE 在...范围' },
  { value: 'NOT RANGE', label: 'NOT RANGE 不在...范围' },
  { value: 'NULL', label: 'NULL 空' },
  { value: 'NOT NULL', label: 'NOT NULL 不为空' },
  { value: 'FIND_IN_SET', label: 'FIND_IN_SET 集合中查询' }
]

const comSearchRenderOptions = [
  { label: '远程筛选', value: 'remoteSelect' },
  { label: '筛选', value: 'select' },
  { label: '日期选择器', value: 'date' },
  { label: '时间选择器', value: 'datetime' },
  { label: '自定义组件', value: 'customRender' },
  { label: '使用插槽', value: 'slot' }
]

const validateOptions = [
  { label: '字符串', value: 'string' },
  { label: '数组', value: 'array' },
  { label: '数字', value: 'number' },
  { label: '日期', value: 'date' },
  { label: '整数', value: 'integer' },
  { label: '浮点数', value: 'float' },
  { label: '对象', value: 'object' },
  { label: '邮箱', value: 'email' },
  { label: '枚举类型', value: 'enum' },
  { label: '网址', value: 'url' },
  { label: 'hex类型', value: 'hex' }
]

const modelTypeOption = [
  { label: '整型(integer)', value: 'integer' },
  { label: '浮点型(float)', value: 'float' },
  { label: '布尔型(boolean)', value: 'boolean' },
  { label: 'array类型(array)', value: 'array' },
  { label: 'stdclass对象(Object)', value: 'object' },
  { label: '序列化类型(serialize)', value: 'serialize' },
  { label: 'json类型(json)', value: 'json' },
  { label: '时间戳(timestamp)', value: 'timestamp' },
  { label: '日期(datetime)', value: 'datetime' }
]

const fieldItemsOption = computed(() =>
  props.fieldItems.map((item) => ({
    label: item.comment + '(' + item.name + ')',
    value: item.name
  }))
)

// enum/set 默认值联动
const enumSetOptions = computed(() => {
  const t = (fieldItem.value && fieldItem.value.length) || ''
  const values = []
  const regex = /'([^']*)'/g
  let m
  while ((m = regex.exec(t)) !== null) values.push(m[1])
  if (!values.length) {
    return t
      .split(',')
      .map((s) => s.trim())
      .filter((s) => s)
  }
  return values
})

const enumDefaultSingle = computed({
  get() {
    if (!fieldItem.value) return ''
    return fieldItem.value.default || ''
  },
  set(v) {
    if (!fieldItem.value) return
    fieldItem.value = { ...fieldItem.value, defaultType: 'INPUT', default: v }
  }
})

const enumDefaultMultiple = computed({
  get() {
    if (!fieldItem.value) return []
    const d = fieldItem.value.default
    if (!d) return []
    if (Array.isArray(d)) return d
    return String(d)
      .split(',')
      .map((s) => s.trim())
      .filter((s) => s)
  },
  set(arr) {
    if (!fieldItem.value) return
    const val = Array.isArray(arr) ? arr.join(',') : ''
    fieldItem.value = { ...fieldItem.value, defaultType: 'INPUT', default: val }
  }
})

function remoteSubmit(value) {
  dialogVisible.value = false
  fieldItem.value = { ...fieldItem.value, remoteConfig: value }
}

// MySQL 字段类型（英文，label 与 value 一致）
const mysqlTypeOptions = [
  'tinyint',
  'smallint',
  'mediumint',
  'int',
  'bigint',
  'float',
  'double',
  'decimal',
  'char',
  'varchar',
  'text',
  'mediumtext',
  'longtext',
  'enum',
  'set',
  'date',
  'datetime',
  'timestamp',
  'time',
  'year',
  'binary',
  'varbinary',
  'blob',
  'tinyblob',
  'mediumblob',
  'longblob',
  'json',
  'bit',
  'bool',
  'boolean'
]

// 兼容旧格式：如 "set('0','1')"、"enum('a','b')"、"varchar(255)"、"decimal(10,2)"
function parseLegacyType(t) {
  if (!t || typeof t !== 'string') return null
  const match = /^\s*([a-zA-Z_]+)\s*\((.*)\)\s*$/.exec(t)
  if (!match) return null
  const base = match[1].toLowerCase()
  const argsRaw = match[2].trim()

  // enum/set: 直接把括号内内容原样放入 length，precision 清空
  if (base === 'enum' || base === 'set') {
    return { type: base, length: argsRaw, precision: '' }
  }

  // 其他带长度/精度的类型：支持 "(m)" 或 "(m,n)"
  const parts = argsRaw.split(',').map((s) => s.trim())
  if (parts.length === 2) {
    const m = parts[0].replace(/^'|"|`|\(|\)$/g, '')
    const n = parts[1].replace(/^'|"|`|\(|\)$/g, '')
    return { type: base, length: m, precision: n }
  }
  if (parts.length === 1) {
    const m = parts[0].replace(/^'|"|`|\(|\)$/g, '')
    return { type: base, length: m }
  }
  return null
}

// 监听 type，若为旧格式则自动转换为新方案字段
watch(
  () => fieldItem.value && fieldItem.value.type,
  (newType) => {
    if (!newType) return
    // 仅当包含括号时认为是旧格式
    if (typeof newType === 'string' && newType.includes('(') && newType.includes(')')) {
      const parsed = parseLegacyType(newType)
      if (parsed) {
        fieldItem.value = {
          ...fieldItem.value,
          type: parsed.type,
          length: parsed.length !== undefined ? parsed.length : fieldItem.value.length,
          precision: parsed.precision !== undefined ? parsed.precision : fieldItem.value.precision
        }
      }
    }
  },
  { immediate: true }
)
</script>

<style scoped lang="scss">
.tab-pane-content {
  height: calc(100vh - 280px);
  overflow: auto;
  padding: 0 10px;

  //&::-webkit-scrollbar {
  //  display: none;
  //}
  //
  //&:hover {
  //  &::-webkit-scrollbar {
  //    display: block;
  //  }
  //}
}
</style>
